package com.sky.aspect;

import com.sky.annotations.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

//Aop切面编程
@Aspect // 切面
@Component // 交给ioc容器管理
@Slf4j // 日志
public class AutoFillAspect {

//    定义一个切点
    @Pointcut("execution( * com.sky.mapper.*.*(..)) && @annotation(com.sky.annotations.AutoFill)")
    public void AutoPointCut(){}

//    通知在原方法运行前运行
    @Before("AutoPointCut()")
    public void autoFill(JoinPoint joinPoint){
        log.info("aop运行...");
//        获取当前被拦截的方法的类型
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        AutoFill fill = signature.getMethod().getAnnotation(AutoFill.class);
//        这个就是注解的”方法名“
        OperationType value = fill.value();

//        获取当前被拦截方法的参数
        Object[] args = joinPoint.getArgs();
        if (args.length == 0 || args == null){
            return;
        }
//        默认第一位是对象类型
        Object parma = args[0];

//        准备赋值的时间对象
        LocalDateTime now = LocalDateTime.now();
        Long currentId = BaseContext.getCurrentId();

//        通过反射获取到方法
        try {
//            通过对象去获取所属于的类，再通过类去获取类当中的方法，                  类的方法名字                类的参数类型
            Method setCreateTime = parma.getClass().getMethod(AutoFillConstant.SET_CREATE_TIME, LocalDateTime.class);
            Method setCreateUser = parma.getClass().getMethod(AutoFillConstant.SET_CREATE_USER, Long.class);
            Method setUpdateTime = parma.getClass().getMethod(AutoFillConstant.SET_UPDATE_TIME, LocalDateTime.class);
            Method setUpdateUser = parma.getClass().getMethod(AutoFillConstant.SET_UPDATE_USER, Long.class);
            if (value == OperationType.INSERT){
//            需要插入四个            为那个对象   值是什么
                setCreateTime.invoke(parma   ,now);
                setUpdateTime.invoke(parma,now);
                setCreateUser.invoke(parma,currentId);
                setUpdateUser.invoke(parma,currentId);
            }else if (value == OperationType.UPDATE){
//            需要插入两个
                setUpdateUser.invoke(parma,currentId);
                setUpdateTime.invoke(parma,now);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }


    }
}
